using System;
using System.BusinessObjects.Transactions;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.IO;
using Blazing.WebFacade;
using Blazing.BusinessObjects.Cms;
using Blazing.BusinessObjects.Tagging;
using MySql.Data.MySqlClient;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Mapping;
using NHibernate.Tool.hbm2ddl;
using System.Web.UI.WebControls;
using Blazing.BusinessObjects.Locations;

namespace Blazing.UI.Cms.Admin
{
	public partial class InstallSchema : System.Web.UI.Page
	{

		protected void Page_Load(object sender, EventArgs e)
		{
            if (!Page.IsPostBack)
            {
                NHibernate.Cfg.Configuration cfg = new NHibernate.Cfg.Configuration();
                cfg.Configure();

                List<string> tableList = new List<string>();
                List<ListItem> listItems = new List<ListItem>();

                foreach (PersistentClass classTable in cfg.ClassMappings)
                {
                    tableList.Add(classTable.Table.Name);
                    listItems.Add(new ListItem(classTable.Table.Name));
                }
                foreach (Collection collectionTable in cfg.CollectionMappings)
                {
                    if (collectionTable.CollectionTable != null && !string.IsNullOrEmpty(collectionTable.CollectionTable.Name) && !tableList.Contains(collectionTable.CollectionTable.Name))
                    {
                        tableList.Add(collectionTable.CollectionTable.Name);
                        listItems.Add(new ListItem(collectionTable.CollectionTable.Name));
                    }
                }

                listItems.Sort(new Comparison<ListItem>(delegate(ListItem item1, ListItem item2)
                    {
                        return string.Compare(item1.Value, item2.Value);
                    }));

                OptGroupDropDownList1.AddOptGroup("CMS Tables", listItems.ToArray());
            }
		}

        protected void ButtonInstall_Click(object sender, EventArgs e)
        {
            Configuration cfg = new Configuration();
            cfg.Configure();

            ISessionFactory factory = cfg.BuildSessionFactory();
            ISession command = factory.OpenSession();
            ITransaction transaction = null;
            if (!(command.Connection is System.Data.SqlClient.SqlConnection))
                transaction = command.BeginTransaction();

            try
            {
                SchemaExport ex = new SchemaExport(cfg);
                ex.Execute(true, true, false, command.Connection, null);

                /**********************************************
                 * Add Default Data
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
                if (!FileUploadXmlData.HasFile)
                {
                    DefaultData.Install();
                }
                else
                {
                    DataSet set = new DataSet();
                    set.ReadXml(FileUploadXmlData.FileContent);

                    ImportData(set, command);
                }
                if(transaction != null)
                    transaction.Commit();
            }
            catch (Exception ex)
            {
                if (transaction != null)
                    transaction.Rollback();
                LabelStatus.Text = ex.Message;
            }

            LabelStatus.Visible = true;
        }

        protected void ButtonDownloadJSON_Click(object sender, EventArgs e)
        {
            StringBuilder dataStream = new StringBuilder();
            StringBuilder dataErrors = new StringBuilder();

            StringBuilder selectAllTableData = new StringBuilder();
            List<string> tableList = new List<string>();

            foreach (ListItem li in OptGroupDropDownList1.Items)
            {
                if (li.Selected == true)
                {
                    tableList.Add(li.Value);
                    selectAllTableData.AppendFormat("select * from {0};", li.Value);
                }
            }

            IDataAdapter mySqlAdapter = null;
            Type dbAdapterType = null;

            if (UnitOfWork.CurrentSession.Connection is MySqlConnection)
                dbAdapterType = Type.GetType("MySql.Data.MySqlClient.MySqlDataAdapter");
            else if (UnitOfWork.CurrentSession.Connection is System.Data.SqlClient.SqlConnection)
                dbAdapterType = typeof(System.Data.SqlClient.SqlDataAdapter);
            else
                throw new ApplicationException(string.Format("Unsupported db connection type. {0}", UnitOfWork.CurrentSession.Connection.GetType()));

            if (dbAdapterType == null)
                dbAdapterType = typeof(MySql.Data.MySqlClient.MySqlDataAdapter);

            mySqlAdapter = (IDbDataAdapter)Activator.CreateInstance(dbAdapterType, selectAllTableData.ToString(), UnitOfWork.CurrentSession.Connection);

            DataSet export = new DataSet("BlazingCMS");
            mySqlAdapter.Fill(export);

            for (int i = 0; i < export.Tables.Count;i++ )
            {
                export.Tables[i].TableName = tableList[i];
            }

            Response.ContentType = "text/plain";
            Response.AppendHeader("Content-Disposition", string.Format("attachment; filename=BlazingCMS{0}.txt", DateTime.Now.ToString("yyMMdd")));

            export.WriteXml(Response.OutputStream);

            Response.End();
        }

        protected void ButtonImport_Click(object sender, EventArgs e)
        {
            Configuration cfg = new Configuration();
            cfg.Configure();

            ISessionFactory factory = cfg.BuildSessionFactory();
            ISession command = factory.OpenSession();
            ITransaction transaction = command.BeginTransaction();

            try
            {
                DataSet set = new DataSet();
                set.ReadXml(FileUploadXmlData.FileContent);

                ImportData(set, command);

                transaction.Commit();
                LabelStatus.Text = "Data successfully imported.";
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                LabelStatus.Text = ex.Message;
            }

            LabelStatus.Visible = true;

        }

        private void ImportData(DataSet set, ISession command)
        {
            IDbCommand insertCommand = command.Connection.CreateCommand();

            //defer forign key checks
            //(this is more of a temporary measure and probably only works with mysql)
            string disableContraints = "";
            string enableContraints = "";
            if (command.Connection is MySqlConnection)
            {
                disableContraints = "SET FOREIGN_KEY_CHECKS=0;";
                enableContraints = "SET FOREIGN_KEY_CHECKS=1;";
            }
            else if (command.Connection is System.Data.SqlClient.SqlConnection)
            {
                disableContraints = "EXEC sp_MSforeachtable @command1='ALTER TABLE ? NOCHECK CONSTRAINT ALL';";
                enableContraints = "EXEC sp_MSforeachtable @command1='ALTER TABLE ? CHECK CONSTRAINT ALL';";
            }

            insertCommand.CommandText = disableContraints;
            insertCommand.ExecuteNonQuery();

            foreach (DataTable tab in set.Tables)
            {
                string insertBuilder = "insert into {0}({1}) values ({2});";
                string variableFormat = "?p{0}";
                string columns = "";
                string variables = "";

                List<string> paramNames = new List<string>();

                for (int i = 0; i < tab.Columns.Count; i++)
                {
                    columns += (i > 0 ? "," : "") + tab.Columns[i];
                    variables += (i > 0 ? "," : "") + string.Format(variableFormat, i);
                    paramNames.Add(string.Format(variableFormat, i));
                }

                insertCommand.CommandText = string.Format(insertBuilder, tab.TableName, columns, variables);

                foreach (DataRow row in tab.Rows)
                { //clears the parameter values for the current sql statement and adds the values for the current row
                    insertCommand.Parameters.Clear();

                    for (int i = 0; i < tab.Columns.Count; i++)
                    {
                        IDataParameter curPar = insertCommand.CreateParameter();
                        curPar.Direction = ParameterDirection.Input;
                        curPar.ParameterName = paramNames[i];

                        if (tab.Columns[i].ColumnName.ToLower() == "rowstamp")
                            curPar.Value = DateTime.Parse(row[i].ToString());
                        else
                            curPar.Value = row[i];
                        insertCommand.Parameters.Add(curPar);
                    }
                    insertCommand.ExecuteNonQuery();
                }
            }

            //enable forign key checks
            insertCommand.Parameters.Clear();
            insertCommand.CommandText = enableContraints;
            insertCommand.ExecuteNonQuery();
        }

        public void ImportBlogML()
        {
            Stream xml = FileUploadXmlData.FileContent;
            ITransaction trans = UnitOfWork.CurrentSession.BeginTransaction();

            try
            {

                BlogMLController controller = new BlogMLController();
                controller.Import(xml);

                trans.Commit();

            }
            catch (Exception ex)
            {
                LabelStatus.Text = ex.Message;
                trans.Rollback();
            }


            LabelStatus.Visible = true;
        }

        protected void ButtonImportBlogML_Click(object sender, EventArgs e)
        {
            ImportBlogML();
        }
	}
}
